package com.csproj.basic.service;

import com.csproj.basic.BasicService;
import com.csproj.basic.domain.Area;
import com.csproj.basic.domain.Container;
import com.csproj.basic.repository.AreaRepository;
import com.csproj.basic.service.dto.AreaDTO;
import com.csproj.basic.service.dto.ContainerDTO;
import com.csproj.basic.service.mapper.AreaMapper;
import com.csproj.siiat.base.common.dto.BaseDTO;
import com.csproj.siiat.base.common.exception.BaseAppException;
import com.csproj.siiat.base.common.util.FileUtils;
import com.csproj.siiat.security.SecurityUtils;
import com.csproj.system.service.UserInfoService;
import net.logstash.logback.encoder.org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.time.ZonedDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service Implementation for managing Area.
 */
@Service
@Transactional
public class AreaService extends BasicService<AreaDTO> {

    private final Logger log = LoggerFactory.getLogger(AreaService.class);

    private final AreaRepository areaRepository;
    private final UserInfoService userInfoService;
    private final AreaMapper areaMapper;

    public AreaService(AreaRepository areaRepository, AreaMapper areaMapper, UserInfoService userInfoService) {
        this.areaRepository = areaRepository;
        this.areaMapper = areaMapper;
        this.userInfoService = userInfoService;
    }

    /**
     * 保存区域并且返回前端需要发的dto，包括扩展属性createName
     *
     * @param areaDTO
     * @return areaDTO
     * TODO 主要负责从前端接收值
     * TODO DTO的扩展属性，在此方法复制
     */
    public AreaDTO saveAndGetDTO(AreaDTO areaDTO) {
        Area area = areaMapper.toEntity(areaDTO);
        area = save(area);
        areaDTO = areaMapper.toDto(area);
        return areaDTO;
    }

    /**
     * 保存区域
     *
     * @param area
     * @return area
     * TODO 纯粹的保存方法，通用于所有保存业务调用
     * TODO 赋默认值，保存后，检查数据库，是否所有字段都有准确值
     */
    public Area save(Area area) {
        Area entity = areaRepository.findFirstByCodeAndDeletedFlagIsFalse(area.getCode());

        Area block = areaRepository.findFirstByWarehouseIdAndSiteIdAndDeletedFlagIsFalseAndBlockFlagIsTrue(area.getWarehouseId(), area.getSiteId());

        Area unblock = areaRepository.findFirstByWarehouseIdAndSiteIdAndDeletedFlagIsFalseAndUnblockFlagIsTrue(area.getWarehouseId(), area.getSiteId());


        if (StringUtils.isNotBlank(area.getId())) {
            if (entity != null && !entity.getId().equals(area.getId())) {
                throw new BaseAppException(false, "duplicate_name");
            }

        } else if (entity != null) {
            throw new BaseAppException(false, "duplicate_name");
        }

        if (area.getUnblockFlag()) {
            if (StringUtils.isNotBlank(area.getId())) {
                if (unblock != null && !unblock.getId().equals(area.getId())) {
                    throw new BaseAppException(false, "unblock_duplicate");
                }
            } else if (unblock != null) {
                throw new BaseAppException(false, "unblock_duplicate");
            }
        }

        if (area.getBlockFlag()) {
            if (StringUtils.isNotBlank(area.getId())) {
                if (block != null && !block.getId().equals(area.getId())) {
                    throw new BaseAppException(false, "block_duplicate");
                }
            } else if (block != null) {
                throw new BaseAppException(false, "block_duplicate");
            }
        }

        area.setCreationTime(ZonedDateTime.now());
        area.setCreatorUserId(SecurityUtils.getCurrentUserId());
        area.setDeletedFlag(false);
        return areaRepository.save(area);
    }

    /**
     * 修改区域并且返回前端需要发的dto，包括扩展属性
     *
     * @param areaDTO
     * @return areaDTO
     * TODO 类似SAVE
     */
    public AreaDTO updateAndGetDTO(AreaDTO areaDTO) {
        Area area = areaRepository.findOne(areaDTO.getId());
        if (area == null) {
            throw new BaseAppException(BaseDTO.CODE_PARAM, "id不存在");
        }
        area.setAreaName(areaDTO.getAreaName());

        area = update(area);
        return areaMapper.toDto(area);
    }

    /**
     * 修改区域
     *
     * @param area
     * @return area
     * TODO 类似SAVE
     */
    public Area update(Area area) {
        Area entity = areaRepository.findFirstByCodeAndDeletedFlagIsFalse(area.getCode());
        Area block = areaRepository.findFirstByWarehouseIdAndSiteIdAndDeletedFlagIsFalseAndBlockFlagIsTrue(area.getWarehouseId(), area.getSiteId());

        Area unblock = areaRepository.findFirstByWarehouseIdAndSiteIdAndDeletedFlagIsFalseAndUnblockFlagIsTrue(area.getWarehouseId(), area.getSiteId());

        if (StringUtils.isNotBlank(area.getId())) {
            if (entity != null && !entity.getId().equals(area.getId())) {
                throw new BaseAppException(false, "duplicate_name");
            }

        } else if (entity != null) {
            throw new BaseAppException(false, "duplicate_name");
        }

        if (area.getUnblockFlag()) {
            if (StringUtils.isNotBlank(area.getId())) {
                if (unblock != null && !unblock.getId().equals(area.getId())) {
                    throw new BaseAppException(false, "unblock_duplicate");
                }
            } else if (unblock != null) {
                throw new BaseAppException(false, "unblock_duplicate");
            }
        }

        if (area.getBlockFlag()) {
            if (StringUtils.isNotBlank(area.getId())) {
                if (block != null && !block.getId().equals(area.getId())) {
                    throw new BaseAppException(false, "block_duplicate");
                }
            } else if (block != null) {
                throw new BaseAppException(false, "block_duplicate");
            }
        }
        Area areaDB = findOne(area.getId());
        areaDB.setAreaName(area.getAreaName());
        areaDB.setRadius(area.getRadius());
        areaDB.setLatitude(area.getLatitude());
        areaDB.setLongitude(area.getLongitude());
        areaDB.setCode(area.getCode());
        //  areaDB.setUseType(area.getUseType());
        areaDB.setBlockFlag(area.getBlockFlag());
        areaDB.setUnblockFlag(area.getUnblockFlag());
        areaDB.setWarehouseId(area.getWarehouseId());
        areaDB.setGeoJson(area.getGeoJson());
        areaDB = areaRepository.save(areaDB);
        return areaDB;
    }


    /**
     * TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     *
     * @return the list of entities
     */
    @Transactional(readOnly = true)
    public List<Area> findAll() {
        log.debug("Request to get all Containers");
        List<Area> areaList = areaRepository.findAll();
        return areaList;
    }

    /**
     * 获取所有区域信息
     *
     * @return TODO 返回DTO，包含扩展属性
     * TODO 如果扩展属性不同，可写多个findAllAndGetDTO1、findAllAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public List<AreaDTO> findAllAndGetDTO() {
        List<AreaDTO> areaDTOS = areaMapper.toDto(findAll());
        return areaDTOS;
    }

    /**
     * 根据id，获取区域信息
     *
     * @param id the id of the entity
     * @return the entity
     * <p>
     * TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Area findOne(String id) {
        Area area = areaRepository.findOne(id);
        if (area == null) {
            throw new BaseAppException(BaseDTO.CODE_PARAM, "id有错误");
        }
        return area;
    }


    /**
     * 获取所有区域信息（分页）
     *
     * @return the list of entities
     * <p>
     * TODO 返回纯粹的数据库对象，不包含扩展属性，适用于所有调取业务方法
     */
    @Transactional(readOnly = true)
    public Page<Area> findPageList(Map<String, Object> map, Pageable pageable) {

        Page<Area> result = areaRepository.findPageList(map, pageable);
        return result;
    }

    /**
     * 获取所有区域信息（分页）
     *
     * @return the list of entities
     * <p>
     * TODO 返回DTO，包含扩展属性
     * TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public BaseDTO findPageListAndGetDTO(Map<String, Object> map, Pageable pageable) {
        //根据角色确认查询
        String siteId = userInfoService.getCurrentUserSiteId();

        map.put("siteId", siteId);

        Page<Area> result = findPageList(map, pageable);
        List<Area> areas = result.getContent();
        List<AreaDTO> areaDTOS = areaMapper.toDto(areas);
        extendCompanyName(areaDTOS, "warehouseId", "warehouseName");
        extendSiteName(areaDTOS, "siteId", "siteName");
        return BaseDTO.createBaseDTO(result).setFieldList(areaDTOS);
    }


    /**
     * 根据id，获取区域信息
     *
     * @param id 主键id
     * @return creator、questionTypeName
     * <p>
     * TODO 返回DTO，包含扩展属性
     * TODO 如果扩展属性不同，findPageListAndGetDTO1、findPageListAndGetDTO2，注明扩展的属性
     */
    @Transactional(readOnly = true)
    public AreaDTO findOneAndGetDTO(String id) {
        Area area = findOne(id);
        AreaDTO areaDTO = areaMapper.toDto(area);
        return areaDTO;
    }

    /**
     * 根据id，删除区域信息
     *
     * @param id the id of the entity
     */
    public void delete(String id) {
        areaRepository.delete(id);
    }

    /**
     * 根据机构ids，批量删除区域信息
     *
     * @param ids
     */
    public void deleteIds(String[] ids) {
        areaRepository.deleteIds(ids);
    }

    /**
     * 上传文件
     *
     * @param file
     */
    public String uploadFile(HttpServletRequest request, MultipartFile file) {
        String filePath = FileUtils.excelUpload(request, file, File.separator + "upload" + File.separator + "warehouse");
        return filePath;
    }


}
